package com.zhiqian.community.service;

import com.alibaba.fastjson.JSONObject;
import com.zhiqian.community.dao.MessageMapper;
import com.zhiqian.community.entity.*;
import com.zhiqian.community.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.util.HtmlUtils;

import java.util.*;

@Service
public class MessageService implements CommunityConstant {
    @Autowired
    private MessageMapper messageMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private SensitiveFilter sensitiveFilter;
    @Autowired
    private HostHolder hostHolder;
    @Autowired
    private CommentService commentService;
    @Autowired
    private DiscussPostService discussPostService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 查询会话列表
     *
     * @param user
     * @param page
     * @return
     */
    public List<Map<String, Object>> queryConversationsList(User user, Page page) {
        if (user == null) {
            throw new IllegalArgumentException("参数不能为空");
        }
        List<Map<String, Object>> result = new ArrayList<>(page.getLimit() + 1);
        List<Message> messages = messageMapper.queryConversations(user.getId(), page.getOffset(), page.getLimit());
        messages.stream().forEach(message -> {
            Map<String, Object> map = new HashMap<>(4);
            map.put("message", message);
            User target = message.getFromId().equals(user.getId()) ? userService.getUserById(message.getToId()) : userService.getUserById(message.getFromId());
            map.put("target", target);
            int unreadCount = messageMapper.selectLetterUnreadCount(user.getId(), message.getConversationId());
            map.put("unreadCount", unreadCount);
            int letterCount = selectLetterCount(message.getConversationId());
            map.put("letterCount", letterCount);
            result.add(map);
        });
        return result;
    }

    /**
     * 查询会话详情
     *
     * @param conversationId
     * @param page
     * @return
     */
    public List<Message> queryConversationDetail(String conversationId, Page page) {
        List<Message> messages = messageMapper.queryMessageList(conversationId, page.getOffset(), page.getLimit());
        List<Integer> list = new ArrayList<>();
        messages.stream().forEach(message -> {
            if (message.getStatus() == 0 && message.getToId().equals(hostHolder.getUser().getId())) {
                list.add(message.getId());
            }
        });
        if (!list.isEmpty()) {
            updateLetterStatus(list, 1);
        }
        return messages;
    }

    /**
     * 查询消息未读数量
     *
     * @param userId
     * @param conversationId
     * @return
     */
    public int selectUnreadCount(Integer userId, String conversationId) {
        return messageMapper.selectLetterUnreadCount(userId, conversationId);
    }

    /**
     * 查询用户会话列表总数
     *
     * @param userId
     * @return
     */
    public int selectConversationsCount(Integer userId) {
        return messageMapper.selectConversationsCount(userId);
    }

    /**
     * 查询某会话消息总数
     *
     * @param conversationId
     * @return
     */
    public int selectLetterCount(String conversationId) {
        return messageMapper.selectLetterCount(conversationId);
    }

    /**
     * 发送私信
     *
     * @param user
     * @param target
     * @param content
     * @return
     */
    public int sendLetter(User user, User target, String content) {
        Message message = new Message();
        message.setFromId(user.getId());
        message.setToId(target.getId());
        String conversationId = user.getId().compareTo(target.getId()) > 0 ?
                target.getId() + "_" + user.getId() : user.getId() + "_" + target.getId();
        message.setConversationId(conversationId);
        message.setContent(sensitiveFilter.filter(HtmlUtils.htmlEscape(content)));
        message.setCreateTime(new Date());
        return messageMapper.insertLetter(message);
    }

    /**
     * 修改消息状态
     *
     * @param ids
     * @param status
     * @return
     */
    public int updateLetterStatus(List<Integer> ids, Integer status) {
        return messageMapper.updateLetterStatus(ids, status);
    }

    /**
     * 发送系统通知
     *
     * @param event
     * @return
     */
    public int sendNotification(Event event) {
        Message message = new Message();
        message.setFromId(SYSTEM_USER_ID);
        message.setToId(event.getTargetId());
        message.setConversationId(event.getTopic());
        message.setCreateTime(new Date());
        Map<String, Object> map = new HashMap<>();
        map.put("sourceId", event.getSourceId());
        if (!event.getTopic().equals(TOPIC_FOLLOW)) {
            map.put("entityType", event.getEntityType());
            map.put("entityId", event.getEntityId());
            if (!event.getData().isEmpty()) {
                map.putAll(event.getData());
            }
        }
        message.setContent(JSONObject.toJSONString(map));
        return messageMapper.insertLetter(message);
    }

    /**
     * 给粉丝发送发帖通知
     * @param event
     * @return
     */
    public int sendInform(Event event){
        Integer userId = event.getSourceId();
        String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId);
        Set members = redisTemplate.opsForZSet().range(followerKey,0,-1);
        if (members!=null&& !members.isEmpty()){
            List<Message> list=createList(members,event);
            return messageMapper.insertUserPublishInform(list);
        }
        return 0;
    }

    private List<Message> createList(Set members,Event event) {
        List<Message> result = new ArrayList<>(members.size());
        members.forEach(userId->{
            Message message = new Message();
            message.setFromId(SYSTEM_USER_ID);
            message.setToId((Integer) userId);
            message.setCreateTime(new Date());
            message.setStatus(0);
            message.setConversationId(TOPIC_INFORM);
            Map<String,Object> map = new HashMap(2);
            map.put("postId",event.getEntityId());
            map.put("sourceId",event.getSourceId());
            message.setContent(JSONObject.toJSONString(map));
            result.add(message);
        });
        return result;
    }

    /**
     * 查询用户的通知列表
     *
     * @param userId
     * @return
     */
    public Map<String, Map<String, Object>> selectInformList(Integer userId) {
        Map<String, Map<String, Object>> result = new HashMap<>(4);
        List<Message> informList = getInformList(userId);
        informList.stream().forEach(message -> {
            Map<String, Object> map = new HashMap<>(5);
            Map<String, Integer> content = JSONObject.parseObject(message.getContent(), Map.class);
            map.put("sourceUser", userService.getUserById(content.get("sourceId")));
            map.put("createTime", message.getCreateTime());
            String topic = message.getConversationId();
            map.put("informCount", messageMapper.selectTopicCount(userId, topic));
            map.put("topicUnreadCount",selectUnreadInformCount(userId,topic));
            map.put("entityType", content.get("entityType"));
            result.put(topic, map);
        });
        return result;
    }

    public int selectUnreadInformCount(Integer userId,String topic){
        return messageMapper.selectTopicUnreadCount(userId,topic);
    }

    private List<Message> getInformList(Integer userId) {
        List<Message> result = new ArrayList<>(3);
        Message likeMessage = messageMapper.queryLatestInform(userId, TOPIC_LIKE);
        if (likeMessage != null) {
            result.add(likeMessage);
        }
        Message commentMessage = messageMapper.queryLatestInform(userId, TOPIC_COMMENT);
        if (commentMessage != null) {
            result.add(commentMessage);
        }
        Message followMessage = messageMapper.queryLatestInform(userId, TOPIC_FOLLOW);
        if (followMessage != null) {
            result.add(followMessage);
        }
        Message informMessage = messageMapper.queryLatestInform(userId, TOPIC_INFORM);
        if (informMessage!=null){
            result.add(informMessage);
        }
        return result;
    }

    /**
     * 查询主题详情
     *
     * @param userId
     * @param topic
     * @param page
     * @return
     */
    public List<Map<String, Object>> selectTopicMessageList(Integer userId, String topic, Page page) {
        List<Map<String, Object>> result = new ArrayList<>();
        List<Message> messages = messageMapper.queryTopicMessageList(userId, topic, page.getOffset(), page.getLimit());
        ArrayList<Object> ids = new ArrayList<>();
        messages.forEach(message -> {
            Map<String, Object> map = new HashMap<>(7);
            Map<String, Integer> content = JSONObject.parseObject(message.getContent(), Map.class);
            map.put("sourceUser", userService.getUserById(content.get("sourceId")));
            map.put("createTime", message.getCreateTime());
            map.put("topic", topic);
            map.put("messageId",message.getId());
            map.put("targetComment",null);
            map.put("sourceComment",null);
            if (!topic.equals(TOPIC_FOLLOW)) {
                int postId = content.get("postId");
                if (!topic.equals(TOPIC_INFORM)) {
                    int entityType = content.get("entityType");
                    int entiTyId = content.get("entityId");
                    if (entityType == 2) {
                        Comment comment = commentService.selectCommentById(entiTyId);
                        map.put("targetComment", comment);
                    }
                }
                DiscussPost post = discussPostService.selectDiscussPostById(postId);
                map.put("post", post);
            }
            if (topic.equals(TOPIC_COMMENT)) {
                map.put("sourceComment", commentService.selectCommentById(content.get("sourceCommentId")));
            }
            result.add(map);
            if (message.getStatus()==0){
                ids.add(message.getId());
            }
        });
        if (!ids.isEmpty()){
            messageMapper.updateLetterStatus(ids,1);
        }
        return result;
    }

    public int selectTopicCount(Integer userId, String topic) {
        return messageMapper.selectTopicCount(userId, topic);
    }

    public int selectUserUnreadMessageCount(Integer userId){
        return messageMapper.selectUserUnreadMessageCount(userId);
    }
}
